import dayjs from 'dayjs'
import { request } from '@/utils'
import { defineComponent, onMounted, ref } from '@vue/runtime-core'
import { SyncOutlined, PlusOutlined } from '@ant-design/icons-vue'
import { Button, Drawer, Form, Input, Table, Textarea, Popconfirm, Descriptions, message } from 'ant-design-vue'
import './App.less'

const App = defineComponent(() => {

  const apps = ref([])
  const isEdit = ref(false)
  const editDrawerVisible = ref(false)
  const editAppModel = ref<any>({})
  const tokenDrawerVisible = ref(false)
  const tokenAppModel = ref<any>({})
  const renewDrawerVisible = ref(false)
  const renewModel = ref<any>({ total: { ok: 0, error: 0 } })
  const querying = ref(false)
  const timer = ref()

  const addClick = () => {
    editAppModel.value = {
      oauthScope: 'offline_access BookingsAppointment.ReadWrite.All Calendars.Read Contacts.Read Directory.Read.All Files.Read.All Files.ReadWrite.All Group.Read.All Mail.Read Mail.Send MailboxSettings.Read Notes.Read.All People.Read.All Presence.Read.All Sites.Read.All Tasks.ReadWrite User.Read.All'
    }
    isEdit.value = false
    editDrawerVisible.value = true
  }

  const getApps = () => {
    querying.value = true
    request.get('/azure-app').then(res => {
      apps.value = res.data
    }).finally(() => {
      querying.value = false
    })
  }

  const onFinish = () => {
    request.request({
      url: 'azure-app',
      method: isEdit.value ? 'PUT' : 'POST',
      data: editAppModel.value
    }).then(res => {
      editDrawerVisible.value = false
      message.success('保存成功')
      getApps()
    })
  }

  const openEditDrawer = (record: any) => {
    editAppModel.value = { ...record }
    isEdit.value = true
    editDrawerVisible.value = true
  }

  const openTokenDrawer = (record: any) => {
    tokenAppModel.value = { name: record.name, ...record.msToken }
    tokenDrawerVisible.value = true
  }

  const openRenewDrawer = (record: any) => {
    renewDrawerVisible.value = true
    if (timer.value) {
      clearInterval(timer.value)
    }
    const aciton = () => {
      request.get(`/azure-app-renew/${record.clientId}`).then(({ data }) => {
        data.statistics = Object.keys(data.statistics).map(key => {
          return { name: key, ...data.statistics[key] }
        })
        let total = data.statistics.reduce((previousValue: any, currentValue: any) => {
          previousValue.ok = previousValue.ok + currentValue.ok
          previousValue.error = previousValue.error + currentValue.error
          return previousValue
        }, { ok: 0, error: 0 })
        renewModel.value = { name: record.name, total, ...data }
      })
    }
    timer.value = setInterval(() => {
      aciton()
    }, 1000)
    aciton()
  }

  const closeRenewDrawer = () => {
    if (timer.value) {
      clearInterval(timer.value)
    }
    renewDrawerVisible.value = false
  }

  const startRenew = (record: any) => {
    request.get(`/azure-app-renew/${record.clientId}/start/`).then(res => {
      getApps()
    })
  }

  const stopRenew = (record: any) => {
    request.get(`/azure-app-renew/${record.clientId}/stop/`).then(res => {
      getApps()
    })
  }

  const deleteApp = (record: any) => {
    request.delete(`/azure-app/${record.clientId}`).then(res => {
      getApps()
    })
  }

  onMounted(() => {
    getApps()
  })

  return () => (

    <div class="page-app">

      <div class="toolbar">
        <Button.Group>
          <Button type="primary" onClick={addClick} icon={<PlusOutlined />}>Add a app</Button>
          <Button onClick={getApps} icon={<SyncOutlined />}>Refresh</Button>
        </Button.Group>
      </div>

      <Table
        loading={querying.value}
        bordered={true}
        size="small"
        columns={[
          { title: 'ClientId', dataIndex: 'clientId' },
          { title: 'Code', dataIndex: 'code' },
          { title: 'Name', dataIndex: 'name' },
          {
            title: 'Authorize Status', dataIndex: 'authorizeStatus', customRender: ({ text }: any) => {
              let color = text === 'unauthorized' || text === 'stopped' ? 'red' : 'green'
              return <span style={{ color }}>{text}</span>
            }
          },
          {
            title: 'Renew Status', dataIndex: 'renewStatus', customRender: ({ text }: any) => {
              let color = text === 'stopped' ? 'red' : 'green'
              return <span style={{ color }}>{text}</span>
            }
          },
          {
            title: 'Action', dataIndex: 'action', customRender: ({ record }: any) => {
              return (
                <div class="actions">
                  <a onClick={() => openEditDrawer(record)}>Edit</a>
                  {record.authorizeStatus !== 'refreshing' && (
                    <>
                      <a target="_blank" href={record.authUrl}>Authorize</a>
                      <Popconfirm
                        title="Are you sure delete this app?"
                        okText="Yes"
                        cancelText="No"
                        onConfirm={() => deleteApp(record)}
                      >
                        <a>Delete</a>
                      </Popconfirm>
                    </>
                  )}
                  {
                    record.authorizeStatus === 'refreshing' && (
                      <>
                        <a onClick={() => openTokenDrawer(record)}>View Token</a>
                        {record.renewStatus == 'stopped' && (
                          <a onClick={() => startRenew(record)}>Start Renew</a>
                        )}
                        {record.renewStatus == 'running' && (
                          <>
                            <a onClick={() => openRenewDrawer(record)}>View Renew</a>
                            <a onClick={() => stopRenew(record)}>Stop Renew</a>
                          </>
                        )}
                      </>
                    )
                  }
                </div>
              )
            }
          },
        ]}
        dataSource={apps.value}
        pagination={false}
      />

      <Drawer title={`${isEdit.value ? 'Edit' : 'Add'} App`} width="500" visible={editDrawerVisible.value} onClose={() => editDrawerVisible.value = false}>
        <Form layout="vertical" model={editAppModel.value} onFinish={onFinish} rules={{
          clientId: { required: true, min: 1, max: 64 },
          code: { required: true, min: 1, max: 64 },
          name: { required: true, min: 1, max: 64 },
          clientSecret: { required: true, min: 1, max: 64 },
          oauthScope: { required: true, min: 1, max: 2000 },
        }}>
          <Form.Item label="ClientId" name="clientId">
            <Input v-model={[editAppModel.value.clientId, 'value']} disabled={isEdit.value} />
          </Form.Item>
          <Form.Item label="Code" name="code">
            <Input v-model={[editAppModel.value.code, 'value']} />
          </Form.Item>
          <Form.Item label="Name" name="name">
            <Input v-model={[editAppModel.value.name, 'value']} />
          </Form.Item>
          <Form.Item label="ClientSecret" name="clientSecret">
            <Input v-model={[editAppModel.value.clientSecret, 'value']} />
          </Form.Item>
          <Form.Item label="OAuthScope" name="oauthScope">
            <Textarea autosize v-model={[editAppModel.value.oauthScope, 'value']} />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit">Save</Button>
          </Form.Item>
        </Form>
      </Drawer>

      <Drawer title={`${tokenAppModel.value.name} token`} class="token-drawer" width="500" visible={tokenDrawerVisible.value} onClose={() => tokenDrawerVisible.value = false}>
        <Descriptions layout="vertical" column={1} bordered={true} size="small">
          <Descriptions.Item label="Token Type">{tokenAppModel.value.token_type}</Descriptions.Item>
          <Descriptions.Item label="Scope">{tokenAppModel.value.scope}</Descriptions.Item>
          <Descriptions.Item label="Sign Time">{dayjs(tokenAppModel.value.sign_ts).format('YYYY-MM-DD HH:mm:ss')}</Descriptions.Item>
          <Descriptions.Item label="Expires Time">{dayjs(tokenAppModel.value.expires_ts).format('YYYY-MM-DD HH:mm:ss')}</Descriptions.Item>
          <Descriptions.Item label="Expires In">{tokenAppModel.value.expires_in}</Descriptions.Item>
          <Descriptions.Item label="Ext Expires In">{tokenAppModel.value.ext_expires_in}</Descriptions.Item>
          <Descriptions.Item label="Access Token">{tokenAppModel.value.access_token}</Descriptions.Item>
          <Descriptions.Item label="Refresh Token">{tokenAppModel.value.refresh_token}</Descriptions.Item>
        </Descriptions>
      </Drawer>

      <Drawer title={`${renewModel.value.name} renew`} class="renew-drawer" width="500" visible={renewDrawerVisible.value} onClose={() => closeRenewDrawer()}>
        <p>
          <span>duration: {(dayjs as any).duration(dayjs().diff(renewModel.value.startTime)).format('YYYY-MM-DD HH:mm:ss')}</span>
          <span style={{ margin: '0 20px' }}>ok: {renewModel.value.total.ok}</span>
          <span>error: {renewModel.value.total.error}</span>
        </p>
        <Table
          bordered
          pagination={false}
          size="small"
          dataSource={renewModel.value.statistics}
          columns={[
            { title: 'Name', dataIndex: 'name' },
            { title: 'Ok', dataIndex: 'ok' },
            { title: 'Error', dataIndex: 'error' },
          ]}
        />
      </Drawer>

    </div>

  )
})

export default App